home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
PBLIB1
/
UNITS
/
PBDBOBJ.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-05-03
|
21KB
|
733 lines
{SECTION ..PbDBOBJ }
Unit PbDBOBJ;
INTERFACE
Uses PbMISC, PbOBJS, PbXBASE;
{
Description : xBase DBF file (and my index files) - Object
Author : Howard Richoux
Date : 12/9/93
Last revised: 1/18/94 added non-object support procs (FLIST oriented)
1/30/94 logkeyuse flag to turn on write statements
2/2/94 TURN OFF WRITE ON KEYED_DBF_OBJECT - glitches
2/9/94 implement FETCHWHERE, fix rec count
2/18/94 NEW LIBRARIES
Application : IBM PC and compatibles, done in Turbo Pascal 7
Status : Placed in the Public Domain by HNR Software 1/29/1994
Published in: none
}
{SECTION .DBF_object }
const dbfTESTMODE = 0;
{-}
type DbbuftoPasProc = procedure( var rec );
type PastoDbbufProc = procedure( var rec );
type DBF_object = OBJECT
dbf : XBASE_DBF_object;
filename : string[60];
recsize : integer;
numrecs : longint;
opened : boolean;
CurrRec : longint;
CurrKey : longint; { only really applies to KEYED_DBF }
err : integer;
procedure init(fn : string; recsz : integer; dbfmode : integer);
Function NoError : boolean;
Function exportfielddefn(fldnum : integer) : string;
Procedure fileerror (e : integer);
Function seekn (n : longint) : boolean;
Procedure TOP; {sets CurrRec to 0, cant fail }
Function fetchn (n : longint) : boolean;
Function storen (n : longint) : boolean;
Function exportrecn(n : longint) : string;
Function append : boolean;
Function fetchnext : boolean;
Function fetchwhere(fldspec : string; opr : char; fldval : string):boolean;
Function count : longint;
procedure done;
procedure dump;
end;
{+}
{SECTION .KEYED_DBF_object }
{-}
type KeyPiece_rec = record
keyfld : byte; { which DBF field }
keylen : byte; { how much to use }
keystrxx : string[16] { undecoded string }
end;
const maxkeyfields = 10;
type KEYED_DBF_object = OBJECT(DBF_object)
dbndx : HOLD_object; { the key array }
keytag : string[3]; { also the file extension }
keyspec : string; { 'xxx[3]+yyy+zzz[5]' }
ndxdef : array[1..maxkeyfields] of KeyPiece_rec;
ndxfilename : string[60]; { DBF filename with tag ext }
ndxloaded : boolean;
logkeyuse : boolean; { turn on write statements }
Procedure init (fn : string; recsz : integer;
dbfmode : integer; tag : string;
keyspecstr : string; keymax : integer);
Procedure reloadndx (fn,tag,keyspecstr : string;
keymax : integer);
Function loadndx : boolean;
Procedure dbDecodeNdxPiece(ndxstr :string;var fld,ln :byte);
Procedure dbDecodekeyspec;
Function dbConstructKeyStr : string;
Function createndx : boolean;
Procedure TOP; {sets CurrKey to 0, cant fail }
Function seekn (n : longint) : boolean;
Function fetchn (n : longint) : boolean;
Function storen (n : longint) : boolean;
Function exportrecn(n : longint) : string;
Function append : boolean;
Function fetchnext : boolean;
procedure done;
end;
{+}
{SECTION .Procedures }
Procedure FStringToFList(fstring : string; var x : DBF_object; var FList : HOLD_object);
{[DBF] converts a spec string [FLD1(3)+FLD2] into a FList }
Function FListDataStr(var FList : HOLD_object; var x : DBF_object) : string;
{[DBF] makes a key string out of record data via FList }
{SECTION .zImplementation }
IMPLEMENTATION
{SECTION DBF_object }
procedure DBF_object.init(fn : string; recsz : integer; dbfmode : integer);
begin
filename := fn;
recsize := 0;
opened := false;
CurrRec := 0;
CurrKey := 0;
numrecs := 0;
err := 0;
case dbfmode of
fREADONLY : dbf.init(fn,true);
fREADWRITE : dbf.init(fn,false);
fCREATE : begin
writeln('dbfCREATE function not implemented');
err := -1;
end;
else begin
writeln('Unknown INIT function');
err := -2;
end;
end;
err := dbf.err;
if err = 0 then
begin
opened := true;
numrecs := dbf.dbhead.no_rec;
recsize := dbf.dbhead.rec_bytes;
CurrRec := dbf.db_rec_no;
if (recsz <> 0) and (recsize <> recsz) then
begin
err := -3;
writeln('INIT FAILURE (record size) code=',recsz,
' file=',recsize);
dbf.done;
end;
end;
end;
Function DBF_object.NoError : boolean;
begin
NoError := (err = 0);
end;
Procedure DBF_object.fileerror (e : integer);
begin
err := e;
if not NoError then writeln('DBF_object: ',DOSErrStr(dbf.err),' ',dbf.err);
end;
Function DBF_object.exportfielddefn(fldnum : integer) : string;
var s : string;
i : integer;
fldnam : string;
rtype : char;
width, decp : byte;
begin
s := '';
exportfielddefn := s;
if not opened then
begin
writeln('File not open [exportflddef]');
exit;
end;
i := fldnum;
if (i > 0) and (i <= dbf.no_col) then
begin
dbf.dbFieldInfo(i,fldnam,rtype,width,decp);
s := fldnam + '('+rtype+integerstr(width,3);
if rtype = 'N' then s := s + '.' + integerstr(decp,2);
s := s + ')';
RemoveBlanks(s);
end;
exportfielddefn := s;
end;
Procedure DBF_object.done;
begin
err := 0;
if not dbf.opened then exit;
dbf.done;
err := dbf.err;
end;
Procedure DBF_object.dump;
begin
if not opened then
begin
writeln('File not open [dump]');
exit;
end;
dbf.dbshowstruc;
dbf.dblistrecs;
end;
Function DBF_object.count : longint;
begin
numrecs := dbf.dbhead.no_rec;
count := numrecs;
end;
Function DBF_object.seekn (n : longint) : boolean;
begin
err := 0;
if not opened then
begin
seekn := false;
writeln('File not open [seek]');
exit;
end;
dbf.dbgoto(n);
err := dbf.err;
seekn := NoError;
CurrRec := dbf.db_rec_no;
end;
Procedure DBF_object.TOP;
begin
CurrRec := 0;
dbf.dbgoto(0);
err := 0;
end;
Function DBF_object.fetchn (n : longint) : boolean;
begin
err := 0;
fetchn := false;
if not opened then
begin
writeln('File not open [fetchn]');
exit;
end;
dbf.dbgoto(n);
err := dbf.err;
if dbf.err = 0 then
begin
CurrRec := dbf.db_rec_no;
fetchn := true;
end
else dbf.dbcleardbbuf;
fetchN := NoError;
end;
Function DBF_object.fetchnext : boolean;
var currec : integer;
begin
err := 0;
currec := CurrRec;
fetchnext := false;
if not opened then
begin
writeln('File not open [fetchnext]');
exit;
end;
inc(currec);
fetchnext := fetchN(currec);
end;
Function DBF_object.fetchwhere(fldspec : string; opr : char; fldval : string):boolean;
{ Current implementation - FIELDSPEC can only be a field name
only implementing "=" and doing trim and UpCase }
var found,ok : boolean;
i : longint;
s,fval : string;
begin
found := false; ok := true;
fval := fldval;
trim(fval);
fval := UpCaseStr(fval);
i := CurrRec;
while (i < count) and not found do
begin
inc(i);
ok := fetchn(i);
if ok then
begin
s := dbf.dbstr(dbf.dbfldno(fldspec));
trim(s);
s := UpCaseStr(s);
if compare(s,fval) then
begin
found := true;
end;
end
end;
fetchwhere := found;
end;
Function DBF_object.storen (n : longint) : boolean;
begin
err := 0;
storen := false;
if not opened then
begin
writeln('File not open [storen]');
exit;
end;
dbf.dbposition(n);
err := dbf.err;
if NoError then
begin
dbf.dbrewrite(n);
if NoError then
begin
CurrRec := dbf.db_rec_no;
storen := true;
end;
end;
end;
Function DBF_object.append : boolean;
begin
err := 0;
append := false;
if not opened then
begin
writeln('File not open [append]');
exit;
end;
dbf.dbappend;
err := dbf.err;
if NoError then
begin
CurrRec := dbf.db_rec_no;
numrecs := CurrRec;
append := true;
end;
end;
Function DBF_object.exportrecn (n : longint) : string;
var i : integer;
s,s1 : string;
begin
err := 0;
s := '';
if not opened then
begin
writeln('File not open [exportrec]');
exportrecn := s;
exit;
end;
dbf.dbgoto(n);
if dbf.err = 0 then
begin
for i := 1 to dbf.no_col do
begin
s1 := dbf.dbstr(i);
trim(s1);
s := s + s1;
if i < dbf.no_col then s := s + ',';
end;
end;
exportrecn := s;
end;
{SECTION KEYED_DBF_object }
{Notes: 11/30/93 - compound key support passes a key string instead
of a field name. The key string is a series of field names with optional
length specifiers (in square brackets) joined by plusses. Blanks are all
removed prior to processing. Literals can be placed in the string as long
as they aren't genuine field names (literals are not enclosed in quotes).
[*] means trim blanks from field.
Examples: (quotes are not part of the definition)
'field2'
'field1[3]+field3[*]'
'field3[*]+(+field1[2]+)'
}
Procedure KEYED_DBF_object.init(fn : string; recsz : integer;
dbfmode : integer; tag : string;
keyspecstr : string; keymax : integer);
begin
if (dbfmode <> fREADONLY) and
((tag <> '') or (keyspecstr <> '')) then
begin
err := -10;
writeln('KEYED_DBF_object INIT [',fn,
'] - USE fREADONLY mode with keys.');
exit;
end;
DBF_object.init(fn,recsz,dbfmode);
if dbf.err = 0 then
begin
logkeyuse := false;
CurrKey := 0;
dbndx.init(keymax);
reloadndx(fn,tag,keyspecstr,keymax);
end;
end;
Procedure KEYED_DBF_object.reloadndx (fn,tag,keyspecstr : string;
keymax : integer);
begin
err := 0;
dbndx.done;
dbndx.init(keymax);
ndxloaded := false;
ndxfilename := fn;
ForceExt(ndxfilename,tag);
keytag := tag;
keyspec := keyspecstr;
if (keytag = '') and (keyspec = '') then
begin
if logkeyuse then
writeln('No KEY specified. Access will be by record number.');
exit;
end;
if not loadndx then
begin
if logkeyuse then
begin
writeln('reloadndx Unable to load or create index file for [',
filename,'] [',ndxfilename,']');
writeln(' using tag: [',keytag,
'] DBF field(s): [',keyspec,']');
writeln('Records will be accessed by record number.');
end;
end;
end;
Function KEYED_DBF_object.loadndx : boolean;
var s : string;
loaded : boolean;
begin
err := 0;
ndxloaded := false;
loadndx := true;
if keyspec = '' then exit;
{ writeln('loadndx [',filename,'] [',ndxfilename,']');}
if (keytag <> '') and
(Filedate(filename,'') < Filedate(ndxfilename,'')) then
begin
{writeln('loading index [',ndxfilename,']');}
dbndx.load(ndxfilename);
if dbndx.count < 1 then loadndx := false
else ndxloaded := true;
end;
if not ndxloaded and (keyspec <> '') then
begin
{writeln('creating index [',ndxfilename,'] please wait a few seconds.');}
if not createndx then loadndx := false;
end;
end;
Procedure KEYED_DBF_object.dbDecodeNdxPiece(ndxstr :string;var fld,ln :byte);
var s,s1 : string;
tch : char;
begin
s := ndxstr;
s1 := GetLeftStr(s,'[');
if s[length(s)] = ']' then delete(s,length(s),1);
fld := dbf.dbfldno(s1);
if s = '*' then ln := 0
else if ln = 0 then ln := dbf.dbfldwidth(fld)
else ln := byte(strint(s));
if (dbfTESTMODE > 0) then writeln('NdxPiece: ',ndxstr,' ',fld,' ',ln);
end;
Procedure KEYED_DBF_object.dbDecodekeyspec;
var s,s1 : string;
tch : char;
fld,ln : byte;
i : integer;
begin
s := UpCaseStr(keyspec);
if (dbfTESTMODE > 0) then writeln('Decodekeyspec <',s,'>');
for i := 1 to maxkeyfields do
begin ndxdef[i].keystrxx := ''; ndxdef[i].keyfld := 0;
ndxdef[i].keylen := 0; end;
i := 1;
while (length(s) > 0) and (i <= maxkeyfields) do
begin
fld := 0; ln := 0;
s1 := GetLeftStr(s,'+');
if (dbfTESTMODE > 0) then
writeln('Decodekeyspec1<',s1,'>',i,' ',fld,' ',ln);
if length(s1) > 0 then dbDecodeNdxPiece(s1,fld,ln);
ndxdef[i].keystrxx := s1;
ndxdef[i].keyfld := fld;
ndxdef[i].keylen := ln;
if (dbfTESTMODE > 0) then
writeln('Decodekeyspec2<',s1,'>',i,' ',fld,' ',ln);
inc(i);
end;
end;
Function KEYED_DBF_object.dbConstructKeyStr : string;
var i,j,k : integer;
s,s1 : string;
begin
s := '';
for i := 1 to maxkeyfields do
begin
s1 := '';
j := ndxdef[i].keyfld;
k := ndxdef[i].keylen;
if j > 0 then
begin
if k > 0 then s1 := leftstr(dbf.dbstr(j),k)
else begin
s1 := dbf.dbstr(j);
trim(s1);
end;
end
else if ndxdef[i].keystrxx <> '' then s1 := ndxdef[i].keystrxx;
if (dbfTESTMODE > 0) and (s1 <> '') then
writeln('dbConstructKeyStr ',i,' ',j,' ',k,' <',s1,'>');
s := s + s1;
end;
s1 := s;
trim(s1);
if s1 = '' then s := 'zznone';
dbConstructKeyStr := s;
end;
Function KEYED_DBF_object.createndx : boolean;
var i,error,fldnum,n : integer;
s,s1 : string;
begin
err := 0;
createndx := true;
if keyspec = '' then exit;
dbndx.comment := keyspec;
dbDecodekeyspec;
if (dbfTESTMODE > 0) then
begin
writeln('createndx [',filename,'] [',ndxfilename,']');
writeln('createndx DBF numrecs=',numrecs);
writeln('createndx DBF field [',keyspec,'] field#=',fldnum);
end;
n := numrecs;
if (dbfTESTMODE > 0) then n := 5;
for i := 1 to n do
begin
dbf.dbgoto(i);
error := dbf.err;
if error = 0 then
begin
s := dbConstructKeyStr;
if (dbfTESTMODE > 0) then
writeln('createndx index entry[',s,',',i,']');
dbndx.append(s,i);
end;
end;
dbndx.sort;
if keytag <> '' then dbndx.save(ndxfilename);
ndxloaded := true;
end;
Function KEYED_DBF_object.seekn (n : longint) : boolean;
var ndx : longint;
begin
if n > 0 then ndx := n
else ndx := 1;
CurrKey := n;
if ndxloaded then ndx := dbndx.fetchNumN(n);
seekn := DBF_object.seekn(ndx);
end;
Procedure KEYED_DBF_object.TOP;
begin
CurrRec := 0;
CurrKey := 0;
err := 0;
end;
Function KEYED_DBF_object.fetchn (n : longint) : boolean;
var ndx : longint;
ok : boolean;
begin
ndx := n;
if n > numrecs then
begin
dbf.dbcleardbbuf;
fetchn := false;
exit;
end;
CurrKey := n;
if ndxloaded then ndx := dbndx.fetchNumN(n);
fetchn := DBF_object.fetchn(ndx);
end;
Function KEYED_DBF_object.append : boolean;
var crec : longint;
begin
err := 0;
ndxloaded := false;
append := DBF_object.append;
end;
Function KEYED_DBF_object.fetchnext : boolean;
var crec : longint;
begin
err := 0;
crec := CurrKey;
fetchnext := false;
if not opened then
begin
writeln('File not open [fetchnext]');
exit;
end;
inc(crec);
fetchnext := fetchN(crec);
end;
Function KEYED_DBF_object.storen (n : longint) : boolean;
var ndx : longint;
begin
ndx := n;
CurrKey := n;
if ndxloaded then ndx := dbndx.fetchNumN(n);
storen := DBF_object.storen(ndx);
end;
Function KEYED_DBF_object.exportrecn (n : longint) : string;
var ndx : longint;
begin
ndx := n;
if ndxloaded then ndx := dbndx.fetchNumN(n);
exportrecn := DBF_object.exportrecn(ndx);
end;
Procedure KEYED_DBF_object.done;
begin
dbndx.done;
DBF_object.done;
end;
{SECTION FStringToFList }
Procedure FStringToFList(fstring : string; var x : DBF_object; var FList : HOLD_object);
{[DBF] converts a spec string [FLD1(3)+FLD2] into a FList }
var s,s1,s2 : string;
i,l : integer;
ch : char;
begin
s := UpCaseStr(fstring);
if s = '[*]' then {all fields in order - limit 127}
begin
for i := 1 to x.dbf.no_col do
begin
s1 := '#' + integerstr(i,3);
removeblanks(s1);
FList.append(s1,0);
end;
end
else begin
s := RemoveBrackets(s);
while length(s) > 0 do
begin
s1 := GetLeftStr(s,'+'); {this field}
s2 := GetDelimitedStr(s1,'(',')'); {length string}
l := GetInteger(s2); {length}
if l = 0 then
l := x.dbf.dbfldwidth(x.dbf.dbfldno(s1));
FList.append(s1,l);
end;
end;
end;
{SECTION FListDataStr }
Function FListDataStr(var FList : HOLD_object; var x : DBF_object) : string;
{[DBF] makes a key string out of record data via FList }
var s,nam : string;
i : integer;
len : longint;
begin
s := '';
if FList.count > 0 then
begin
for i := 1 to FList.count do
begin
FList.FetchN(i,nam,len);
s := s + leftstr(x.dbf.dbstr(x.dbf.dbfldno(nam)),len);
end;
end;
FListDataStr := UpCaseStr(trimstr(s));
end;
{SECTION zzInitialization }
begin {initialization}
end.